package com.destin.basic.exception;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局编码异常基类
 *
 * @author: destin
 */
public abstract class AbstractCoderException extends RuntimeException {
    private ErrorCode errorCode;
    private int errorType;
    private Map<String, Object> attributes;

    protected AbstractCoderException(ErrorCode code, int type) {
        super();
        this.errorType = type;
        init(code);
    }

    protected AbstractCoderException(ErrorCode code, String message, int type) {
        super(message);
        this.errorType = type;
        init(code);
    }

    protected AbstractCoderException(ErrorCode code, String message, Throwable ex, int type) {
        super(message, ex);
        this.errorType = type;
        init(code);
    }

    protected void init(ErrorCode code) {
        if (null == code) {
            throw new IllegalArgumentException("Error code is null.");
        }
        this.errorCode = code;
    }

    public int getErrorType() {
        return errorType;
    }

    public ErrorCode getErrorCode() {
        return this.errorCode;
    }

    /**
     * 为异常添加属性
     *
     * @param key
     * @param value
     * @return
     */
    public AbstractCoderException putAttribute(String key, Object value) {
        if (null == attributes) {
            attributes = new HashMap<>();
        }
        attributes.put(key, value);
        return this;
    }

    /**
     * 获取异常属性
     *
     * @return
     */
    public Map<String, Object> getAttributes() {
        return null == attributes ? Collections.emptyMap() : attributes;
    }

    /**
     * 设置异常属性
     *
     * @param attributes
     * @return
     */
    public AbstractCoderException setAttributes(Map<String, Object> attributes) {
        if (null != attributes) {
            this.attributes = attributes;
        }
        return this;
    }

    /**
     * 性能优化：去同步锁去堆栈
     *
     * @return
     */
    @Override
    public Throwable fillInStackTrace() {
        return this;
    }

    @Override
    public String toString() {
        return this.getClass().getTypeName() + "{errorCode=" + errorCode + ", attributes=" + attributes + "}";
    }
}
